#include "sockserver.h"

#include <errno.h> //errno
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>

#include "defcom.h"

ServerSock::ServerSock()
{
}

ServerSock::~ServerSock()
{
}

int ServerSock::CreateServer(const int &port)
{
    struct addrinfo hints, *result;
    memset(&hints, 0, sizeof(hints));
    hints.ai_flags = AI_PASSIVE; //被动打开
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    char number[10];
    sprintf(number, "%d", port);
    int ret = getaddrinfo(NULL, number, &hints, &result);
    if (0 != ret) {
        m_err = gai_strerror(ret);
    } else {
        m_fd = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
        if (-1 == m_fd) {
            m_err = strerror(errno);
        } else {
            int opt = 1;
            int len = sizeof(opt);
            setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR, &opt, len); //设置地址重用

            if (0 != bind(m_fd, result->ai_addr, result->ai_addrlen)) {
                m_err = strerror(errno);
                Close();
            } else {
                if (0 != listen(m_fd, MAXBACKLOG)) {
                    m_err = strerror(errno);
                    Close();
                }
            }
        }
    }
    freeaddrinfo(result);
    return m_fd;
}

int ServerSock::Accept(int timeout, struct sockaddr *addr)
{
    if (timeout > 0) {
        if (TimeoutRWCheck(m_fd, timeout)) {
            m_err = "accept timeout.";
            return -1;
        }
    } else if (timeout < 0) {
        m_err = "timeout value is illegal.";
        return -1;
    }
    struct sockaddr tmpClientAddr;
    struct sockaddr *clientAddr;
    if (NULL == addr) {
        clientAddr = &tmpClientAddr;
    } else {
        clientAddr = addr;
    }

    socklen_t addrlen = sizeof(*clientAddr);
    int ret = -1;
    if (0 < (ret = accept(m_fd, clientAddr, &addrlen))) {
        int rsize = RECV_BUF_SIZE; //接收缓冲区
        int wsize = SEND_BUF_SIZE; //发送缓冲区
        setsockopt(ret, SOL_SOCKET, SO_RCVBUF, &rsize, sizeof(int));
        setsockopt(ret, SOL_SOCKET, SO_SNDBUF, &wsize, sizeof(int));
    } else {
        m_err = strerror(errno);
    }
    return ret;
}
